package com.example.iccil.controller;

import com.example.iccil.common.ErrorCode;
import com.example.iccil.exception.ThrowUtils;
import com.example.iccil.mapper.UserThirdPartyMapper;
import com.example.iccil.model.vo.LoginUserVO;
import com.example.iccil.service.UserService;
import com.example.iccil.service.UserThirdPartyService;
import com.example.iccil.utils.EncryptUtils;
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthGiteeRequest;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 实战演示如何使用JustAuth实现第三方登录
 *
 * @author yadong.zhang (yadong.zhang0415(a)gmail.com)
 * @version 1.0.0
 * @since 1.0.0
 */
@RestController
@RequestMapping("/oauth")
public class JustAuthController {

    @Resource
    private UserService userService;
    @Resource
    private UserThirdPartyService userThirdPartyService;
    @Resource
    private UserThirdPartyMapper userThirdPartyMapper;

    private final ConcurrentHashMap<String, String> authStateMap = new ConcurrentHashMap<>();

    /**
     * 获取授权链接并跳转到第三方授权页面
     *
     * @param source 三方名称
     * @param response response
     * @throws IOException response可能存在的异常
     */
    @RequestMapping("/render/{source}")
    public void renderAuth(@PathVariable("source") String source, HttpServletResponse response, HttpServletRequest request) throws IOException {
        AuthRequest authRequest = getAuthRequest(source);
        String state = AuthStateUtils.createState();
        String encryptState = new EncryptUtils().getEncryptPassword(state);
        authStateMap.put(request.getRequestedSessionId(), encryptState);
        String authorizeUrl = authRequest.authorize(state);
        response.sendRedirect(authorizeUrl);
    }

    /**
     * 用户在确认第三方平台授权（登录）后， 第三方平台会重定向到该地址，并携带code、state等参数
     *
     * @param source 三方名称
     * @param callback 第三方回调时的入参
     * @return 第三方平台的用户信息
     */
    @RequestMapping("/callback/{source}")
    public Object login(@PathVariable("source") String source, AuthCallback callback, HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println("callback = " + callback);
        // 校验state
        String encryptState = new EncryptUtils().getEncryptPassword(callback.getState());
        ThrowUtils.throwIf(!authStateMap.get(request.getRequestedSessionId()).equals(encryptState), ErrorCode.FORBIDDEN_ERROR);
        // 获得三方回调凭证
        AuthRequest authRequest = getAuthRequest(source);
        // 通过凭证获取对应用户信息
        AuthResponse<AuthUser> authResponse = authRequest.login(callback);
        // 校验是否有绑定用户
        String encryptUUID = new EncryptUtils().getEncryptPassword(authResponse.getData().getUuid());
        boolean status = userThirdPartyService.checkBindStatus(encryptUUID, source);
        if (!status) {
            response.sendRedirect("http://localhost:5173/user/thirdPartyLogin?isBind=" + false + "&UUID=" + encryptUUID + "&source=" + source);
            return null;
        }
        // 如果已经绑定
        // 查找绑定账号信息并登录
        LoginUserVO loginUserVO = userService.userThirdPartyLogin(encryptUUID, source, request);
        response.sendRedirect("http://localhost:5173/user/thirdPartyLogin?isBind=" + true + "&UUID=" + encryptUUID + "&source=" + source);
        return null;
    }

    /**
     * 获取授权Request
     *
     * @param source 三方名称
     * @return AuthRequest
     */
    private AuthRequest getAuthRequest(String source) {
        AuthRequest authRequest = null;
        switch (source) {
            case "gitee":
                authRequest = new AuthGiteeRequest(AuthConfig.builder()
                        .clientId("498cfdecca2be1e2a7f6613bff588bc133f7e619aaeb9152a6560ed20dca34cc")
                        .clientSecret("a633a47d2f8c59391dd933ec84a2ce52d4eb2cfeeab0cbe686e454f71af2ca41")
                        .redirectUri("http://localhost:8123/api/oauth/callback/gitee")
                        .build());
                break;
            case "github":
                authRequest = new AuthGiteeRequest(AuthConfig.builder()
                        .clientId("clientId")
                        .clientSecret("clientSecret")
                        .redirectUri("redirectUri")
                        .build());
                break;
            default:
                break;
        }
        // 没有对应的三方登录方式或请求错误
        ThrowUtils.throwIf(authRequest == null, ErrorCode.OPERATION_ERROR);

        return authRequest;
    }

}